iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 25
0
Software Development

30 天的 SFC 學習日誌系列 第 25

Day 25 - DQN實作 - MountainCar(1)

  • 分享至 

  • xImage
  •  

大家好,我是毛毛。
今天是Day 25
換個實驗環境啦~這次是MountainCar~ ヽ(✿゚▽゚)ノ


MountainCar

https://ithelp.ithome.com.tw/upload/images/20201001/20129934hzQUz5zV3W.png
上圖就是Gym中MountainCar-v0的實驗圖

  • 這個環境的狀態是由位置和速度決定
  • Action:
    • 0:向左推車
    • 1:不推車
    • 2:向右推車
  • Reward,除了超過目的地,其餘獎勵都是-1

Import

import os
import gym
import random
import numpy as np
from collections import deque
from keras.optimizers import Adam
from keras.models import Sequential
from keras.layers import Dense, Dropout

引入需要的相關套件。

Deep Q-network

這次也是一樣,先完成DQN的class,可能看起來會跟CartPole的很類似 /images/emoticon/emoticon06.gif

def __init__(self, env, gamma=0.85, epsilon=1.0, epsilon_min=0.01, epsilon_decay=0.995, learning_rate=0.005, tau = .125):
   self.env = env
   self.memory  = deque(maxlen=2000)
   self.gamma = gamma
   self.epsilon = epsilon
   self.epsilon_min = epsilon_min
   self.epsilon_decay = epsilon_decay
   self.learning_rate = learning_rate
   self.tau = tau
   self.eval_net = self.__build_network()
   self.target_net = self.__build_network()

這邊也是在設定神經網路的相關參數,因為eval_net和target_net的神經網路架構是一樣的,所以透過__build_network()去建立這兩個神經網路就好,不用打兩段一樣的程式碼。

def __build_network(self):
   model   = Sequential()
   state_shape  = self.env.observation_space.shape
   model.add(Dense(24, input_dim=state_shape[0], activation="relu"))
   model.add(Dense(48, activation="relu"))
   model.add(Dense(24, activation="relu"))
   model.add(Dense(self.env.action_space.n))
   model.compile(loss="mean_squared_error", optimizer=Adam(lr=self.learning_rate))
   return model

這邊也跟CartPole的時候一樣,在這個function中建立eval_net和target_net,並透過compile函數定義損失函數(loss)、優化函數(optimizer)及成效衡量指標(mertrics)。

def target_replacement(self):
   weights = self.eval_net.get_weights()
   target_weights = self.target_net.get_weights()

   for i in range(len(target_weights)):
       target_weights[i] = weights[i] * self.tau + target_weights[i] * (1 - self.tau)

   self.target_net.set_weights(target_weights)

target_net需要透過eval_net的權重來更新自己的神經網路的權重。
只是這邊不是完全取代舊的權重,而是根據比例去得到新的權重來更新target_net。

def store_transition(self, state, action, reward, new_state, terminal):
   self.memory.append([state, action, reward, new_state, terminal])

這邊是將當下的資訊存起來。

def replay_transition(self):
   batch_size = 32

   if len(self.memory) < batch_size: 
       return

   samples = random.sample(self.memory, batch_size)

   for sample in samples:
       state, action, reward, new_state, terminal = sample
       target = self.target_net.predict(state)

       if terminal:
           target[0][action] = reward
       else:
           Q_future = max(self.target_net.predict(new_state)[0])
           target[0][action] = reward + Q_future * self.gamma

       self.eval_net.fit(state, target, epochs=1, verbose=0)

這裡就是要隨機地選取過去的經驗,來訓練model。

def choose_action(self, state):
   self.epsilon *= self.epsilon_decay
   self.epsilon = max(self.epsilon_min, self.epsilon)
   if np.random.random() < self.epsilon:
       return self.env.action_space.sample()
   return np.argmax(self.eval_net.predict(state)[0])

這邊也是一樣,選取動作透過epsilon-greedy的方法。

def save_weights(self, filename):
   self.eval_net.save_weights(filename)
   print("=================Weights have saved=================")

儲存eval_net的權重。

def load_weights(self, filename):
   self.eval_net.load_weights(filename, by_name=True)

讀取eval_net之前訓練的權重。

def get_weights(self):
   return self.eval_net.get_weights()

得到現在eval_net的權重,用來看權重使否更新到。


今天就先到這啦,明天在來實際跑MountainCar 0(:3 )~ ('、3_ヽ)_
大家明天見/images/emoticon/emoticon29.gif


Reference


上一篇
Day 24 - DQN實作 - CartPole(2)
下一篇
Day 26 - DQN實作 - MountainCar(2)
系列文
30 天的 SFC 學習日誌30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言